#ifndef Font_First
#define Font_First
#ifdef __GNUG__
#pragma interface
#endif

#include "Object.h"
#include "Rectangle.h"
#include "Metric.h"
#include "CType.h"

class OrdCollection;
class Font;
class Collection;
class DevBitmap;
class ObjArray;
class FontEncoding;

enum GrFont {
	eFontTimes,
	eFontHelvetica,
	eFontCourier,
	eFontSymbol,
	eFontChicago,
	eFontAvantgarde,
	eFontBookman,
	eFontSchoolbook,
	eFontNHelvetica,
	eFontPalatino,
	eFontChancery,
	eFontDingbats,

	eFontDefault    =   eFontTimes
};

enum GrFace {
	eFacePlain      = 0,
	eFaceBold       = BIT(0),
	eFaceItalic     = BIT(1),
	eFaceUnderline  = BIT(2),
	eFaceOutline    = BIT(3),
	eFaceShadow     = BIT(4),
};

enum GrHAdjust {
	eAdjHLeft,
	eAdjHCenter,
	eAdjHRight
};

enum GrVAdjust {
	eAdjVBottom,
	eAdjVTop,
	eAdjVBase,
	eAdjVCenter
};

const int cCharsPerFont = 256;

//---- FontFamily --------------------------------------------------------------

class FontFamily : public Object {
public:
	MetaDef(FontFamily);
	FontFamily(GrFont fid);
	~FontFamily();

	const char *Name() const;
	GrFont Fid() const;
	bool Fixed() const;
	Font *MapSizeFace(int, GrFace);
	Font *MapSizeFace2(int size, GrFace face, bool dflt= FALSE);
	void InspectorId(char *buf, int bufSize);
	void CollectParts(Collection*);

protected:
public:
	GrFont fid;
	bool fixed;             // is a fixed character font
	OrdCollection *fmap;
	FontEncoding *encoding;
};

inline GrFont FontFamily::Fid() const
	{ return fid; }
inline bool FontFamily::Fixed() const
	{ return fixed; }

//---- Font --------------------------------------------------------------------

class Font : public Object {
protected:
	u_short cw[cCharsPerFont];        // character widths
	GrFace face;            // style
	short size;             // point size
	short ils;              // interline spacing
	short ht;               // maximum ascender
	short bs;               // maximum descender
	short width;            // max width
	FontFamily *ff;

	Font(FontFamily*, short size, GrFace face);

public:
	MetaDef(Font);

	friend Font *new_Font(GrFont fid, int size, GrFace face= eFacePlain);
	friend Font *new_Font(GrFont fid, int size, GrFace face, bool real);

	int Width(u_int c) const
		{ return cw[c]; }
	int Width(int c) const
		{ return cw[(u_int)c]; }
	int Width(const byte*, int l= -1) const;
	int Width(const char *s, int l= -1) const
		{ return Width((const byte*)s, l); }
	int MaxWidth(int l= 1);
	Metric GetMetric(const byte *s, int l= -1) const;
	Metric GetMetric(const char *s, int l= -1) const
		{ return GetMetric((const byte*)s, l); }
	Metric GetMetric(u_int c) const;
	Metric GetMetric(int c) const
		{ return GetMetric((byte)c); }
	Rectangle BBox(const byte *s, int l= -1) const;
	Rectangle BBox(const char *s, int l= -1) const
		{ return BBox((const byte*)s, l); }
	Rectangle BBox(u_int c, Point pos) const;
	Rectangle BBox(int c, Point pos) const
		{ return BBox((byte)c, pos); }
	Point AdjustString(const byte *s, Point p, GrVAdjust v, GrHAdjust h) const;
	Point AdjustString(const char *s, Point p, GrVAdjust v, GrHAdjust h) const
		{ return AdjustString((const byte*)s, p, v, h); }

	int Ascender() const
		{ return ht; }
	int Descender() const
		{ return bs; }
	int Size() const
		{ return size; }
	GrFace Face() const
		{ return face; }
	int Spacing() const
		{ return ils; }

	GrFont Fid() const
		{ return ff->Fid(); }
	bool Fixed() const
		{ return ff->Fixed(); }
	const char *Name() const
		{ return ff->Name(); }
	const FontEncoding *Encoding() const
		{ return ff->encoding; }

	Font *WithFace(GrFace face) const;
	Font *WithSize(int size) const;

	virtual DevBitmap *CharAsBitmap(u_int, Point *offset);

	const char *AsString();
	u_long Hash();
	bool IsEqual(Object*);
	OStream &PrintOn(OStream&);
	Object *ReadAndMap(IStream&);
};

extern Font
	*gSysFont,
	*gApplFont,
	*gFixedFont;

//---- FontManager -------------------------------------------------------------

class FontManager : public Object {
public:
	MetaDef(FontManager);
	FontManager();
	~FontManager();

	bool Init();        // returns TRUE on error

	virtual Font *MapFont(GrFont fid, int size, GrFace face);
	virtual Font *MakeFont(FontFamily*, int size, GrFace face, bool dflt= FALSE);
	virtual Font *ScaleFont(FontFamily *ff, int, GrFace);

	FontFamily *MapFamily(GrFont fid);
		
	const char *StyleString(GrFace face) const;

	GrFont NameToId(const char *fontname) const;
	const char *IdToName(GrFont fid) const;
	void CollectParts(Collection*);

protected:
	ObjArray *fmap;
};

extern FontManager *gFontManager;

#endif

